<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>球</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        body {
            overflow: hidden;
        }

        #canvas_div {
            width: 100vw;
            height: 100vh;
        }
    </style>
    <script>
        let config = {
            width: 700,//宽度
            height: 700,//高度
            tagsNum: 50,//标签数量
            RADIUS: 200,//球的半径
            speedX: Math.PI / 360,//球一帧绕x轴旋转的角度
            speedY: Math.PI / 360,//球-帧绕y轴旋转的角度
            tags: [],
            CX: 700 / 2,
            CY: 700 / 2,
            index: 0,
            init() {
                for (let i = 0; i < this.tagsNum; i++) {
                    let tag = {};
                    let k = -1 + (2 * (i + 1) - 1) / this.tagsNum;
                    let a = Math.acos(k);
                    let b = a * Math.sqrt(this.tagsNum * Math.PI)//计算标签相对于球心的角度
                    tag.text = i + 'tag';
                    tag.x = this.CX + this.RADIUS * Math.sin(a) * Math.cos(b);//根据标签角度求出标签的x,y,z坐标
                    tag.y = this.CY + this.RADIUS * Math.sin(a) * Math.sin(b);
                    tag.z = this.RADIUS * Math.cos(a);
                    this.tags.push(tag);
                }
            },
            rotateX(angleX) {
                var cos = Math.cos(angleX);
                var sin = Math.sin(angleX);
                for (let tag of this.tags) {
                    var y1 = (tag.y - this.CY) * cos - tag.z * sin + this.CY;
                    var z1 = tag.z * cos + (tag.y - this.CY) * sin;
                    tag.y = y1;
                    tag.z = z1;
                }
            },
            rotateY(angleY) {
                var cos = Math.cos(angleY);
                var sin = Math.sin(angleY);
                for (let tag of this.tags) {
                    var x1 = (tag.x - this.CX) * cos - tag.z * sin + this.CX;
                    var z1 = tag.z * cos + (tag.x - this.CX) * sin;
                    tag.x = x1;
                    tag.z = z1;
                }
            },
            update(event) {
                var x = event.clientX - this.CX;
                var y = event.clientY - this.CY;
                this.speedX = x * 0.0001 > 0 ? Math.min(this.RADIUS * 0.00002, x * 0.0001) : Math.max(-this.RADIUS * 0.00002, x * 0.0001);
                this.speedY = y * 0.0001 > 0 ? Math.min(this.RADIUS * 0.00002, y * 0.0001) : Math.max(-this.RADIUS * 0.00002, y * 0.0001);
                this.rotateX(this.speedX);
                this.rotateY(this.speedY);
                let max = 0;
                let index = 0;
                for (let i = 1; i < this.tags.length - 1; i++) {
                    if (max <= this.tags[i].z) {
                        max = this.tags[i].z;
                        index = i;
                    }
                }
                if (index != this.index) {
                    this.index = index;
                    document.dispatchEvent(new CustomEvent("changeIndex", {
                        detail: { tag: this.tags[index] }
                    }));
                }
            }

        }
    </script>
</head>

<body>
    <div id="canvas_div">
        <canvas id="canvas"></canvas>
    </div>
    <script>
        /** @type {HTMLCanvasElement} */
        let canvas = document.getElementById("canvas")
        let ctx = canvas.getContext("2d")
        let width = canvas.width = 700;
        let height = canvas.height = 700;
        let clickFlag = false;
        let mouseEven = {};
        let maxText = "";
        config.width = width;
        config.height = height;
        config.RADIUS = 300
        config.CX = width / 2 ;
        config.CY = height / 2;
        config.tagsNum = 50
        config.init()

        let topleft = { clientX: config.width, clientY: config.height }
        let topright = { clientX: config.width, clientY: 0 }
        let bottomleft = { clientX: 0, clientY: config.height }
        let bottomright = { clientX: 0, clientY: 0 }
        let index = 0;
        let direction = [topleft, topright, bottomright,bottomleft];
        setInterval(function () {
            index++;
            if (index > direction.length-1) {
                index = 0;
            }
        }, 10000);

        function update() {
            ctx.fillStyle = "#112a"
            ctx.fillRect(0, 0, width, height);
            ctx.fill()

            for (const tag of config.tags) {
                ctx.save()
                let fs = 20 * (600 / (600 - tag.z));
                ctx.font = fs + "px 微软雅黑"
                ctx.globalAlpha = ((400 + tag.z) / 600);
                let strW = ctx.measureText(tag.text);
                if (mouseEven.clientX >= tag.x && mouseEven.clientX <= tag.x + strW.width && mouseEven.clientY >= tag.y - fs && mouseEven.clientY <= tag.y) {
                    ctx.fillStyle = "red"
                } else {
                    ctx.fillStyle = "blue"
                }
                if (tag.text == maxText) {
                    ctx.fillStyle = "green"
                }
                ctx.fillText(tag.text, tag.x - strW.width / 2, tag.y)
                ctx.restore()
            }

            requestAnimationFrame(update)
            // config.update({ clientX: width / 2, clientY: height / 2 - 100 })
            config.update(direction[index])
        }
        update();
        window.onresize = function () {
            width = canvas.width = window.innerWidth;
            height = canvas.height = window.innerHeight;
        }
        canvas.addEventListener("mousemove", function (e) {
            mouseEven = e;
        })
        document.addEventListener("changeIndex", function (e) {
            console.log("changeIndex", e.detail.tag.text)
            maxText = e.detail.tag.text;
        })
        document.addEventListener("keydown", function (e) {
            console.log(123)
            config.update(mouseEven)
        })


    </script>
</body>

</html>